package com.wetool.service.commodity;

import java.sql.Timestamp;
import java.util.List;
import javax.transaction.Transactional;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import com.wetool.common.commodity.CommodityResult;
import com.wetool.common.model.Message;
import com.wetool.entity.Commodity;
import com.wetool.entity.SplitCommodityRule;
import com.wetool.entity.invoicing.InvoicingCommodity;
import com.wetool.entity.invoicing.Supplier;
import com.wetool.exception.CategoryNotFindException;
import com.wetool.exception.MerchantNotLoginException;
import com.wetool.jpa.CommodityEventHandler;
import com.wetool.jpa.CommodityRepo;
import com.wetool.jpa.dto.CommodityDtoRepo;
import com.wetool.jpa.dto.CommodityDtoShowRepo;
import com.wetool.model.CommodityReceive;
import com.wetool.model.SearchParam;
import com.wetool.model.dto.CommodityAdds;
import com.wetool.model.dto.CommodityDto;
import com.wetool.model.dto.CommodityDtoShow;
import com.wetool.model.dto.CommodityModifys;
import com.wetool.push.api.model.model.CommodityPushMessage;
import com.wetool.service.invoicing.InventoryService;
import com.wetool.service.invoicing.InvoicingCommodityNewService;
import com.wetool.spec.CommodityDtoSpec;
import com.wetool.utils.BeanUtils;

@Service
public class CommodityNewService {
	private static final Logger logger = LogManager.getLogger(CommodityNewService.class);
	
	@Autowired
	private CommodityRepo commodityRepo;
	
	@Autowired
	private CategoryService categoryService;
	
	@Autowired
	private CommodityDtoRepo commodityDtoRepo;
	
	@Autowired
	private RuleCheckService ruleCheckService;
	
	@Autowired
	private CommodityDtoShowRepo commodityDtoShowRepo;
	
	@Autowired
	private CommodityEventHandler commodityEventHandler;
	
	@Autowired
	private InventoryService invoicingRecordService;
	
	@Autowired
	private InvoicingCommodityNewService invoicingCommodityNewService;
	
	@Autowired
	private PushService pushService;
	
	@Autowired
	private SplitCommodityRuleService splitCommodityRuleService;
	
	/**
	 * pos 端列表查询
	 * @param merchantId
	 * @param params
	 * @param p
	 * @return
	 * @throws MerchantNotLoginException
	 * @throws CategoryNotFindException
	 */
	public Page<CommodityDto> find(Long merchantId, SearchParam params, Pageable p) throws MerchantNotLoginException, CategoryNotFindException {
		if(merchantId == null ) {	// 判断商家ID是否为null
			logger.debug("商家商品业务处理类中（商品列表查询） -> 商家ID为空");
			throw new MerchantNotLoginException("商家商品业务处理类中（商品列表查询） -> 商家ID为空");	// 抛出商家未登录异常
		}
		Long[] categoryIds = categoryService.getIds(merchantId, params.getCategoryId());//获取商品分类和商品分类下打子节点
		CommodityDtoSpec spec = new CommodityDtoSpec(merchantId, params, categoryIds);
		Page<CommodityDto> page = commodityDtoRepo.findAll(spec, p);
		page.getContent().stream().forEach(cd -> {cd.setPicPath(cd.path()); cd.setNumber(cd.number(params.getShopId())); cd.setResources(null);cd.setInvoicingCommodity(null);});
		return page;
	}

	/**
	 * 根据商品编号查询商品信息
	 * @param id　商家库商品id
	 * @param shopId 店铺id
	 */
	public Message<CommodityDtoShow> findOne(Long merchantId, Long id, Long shopId) {
		if (merchantId == null) {
			logger.debug("根据商品编号查询商品信息 商家ID为空");
			return new Message<>(CommodityResult.MERCHANTNOTLOGIN);
		}
		logger.info("根据商品编号查询商品信息 . 参数　商品id【{}】,　店铺id【{}】", id, shopId);
		CommodityDtoShow commodityDtoShow = commodityDtoShowRepo.findOne(id);//查询信息DTO封装19
		if (commodityDtoShow == null ) {
			return new Message<>(CommodityResult.COMMODITYNOTFIND);
		}
		Double buyingCost = invoicingRecordService.getBuyingCost(shopId, id);//店铺库存成本统计
		Double sellingCost = invoicingRecordService.getSellingPrice(shopId, id);//店铺销售成本统计
		logger.info("根据商品编号查询商品信息 . 返回　库存成本【{}】,预售成本【{}】", buyingCost, sellingCost);
		commodityDtoShow.setBuyingCost(buyingCost);//库存成本统计
		commodityDtoShow.setSellingCost(sellingCost);//销售成本统计
		/* 获取库存数量 */
		InvoicingCommodity ic = invoicingCommodityNewService.getByCommodityIdAndShopId(id, shopId);
		commodityDtoShow.setInventoryNumber(ic.getInventoryNumber());
		commodityDtoShow.setResource(commodityDtoShow.resource());//图片数据处理
		String categoryName = categoryService.getById(commodityDtoShow.getCategoryId());
		commodityDtoShow.setCategoryName(categoryName);//分类名称
		Supplier supplier = invoicingCommodityNewService.getSupplierByCommodityIdAndShopId(id, shopId);//供应商信息查询
		logger.info("根据商品编号查询商品信息 . 查询商品库存供应商信息【{}】", supplier);
		if (supplier != null) {
			commodityDtoShow.setSupplierId(supplier.getId());
			commodityDtoShow.setSupplierName(supplier.getSupplierName());
		}
		return new Message<>(CommodityResult.SUCCESS,commodityDtoShow);
	}

	/**
	 * 根据商品id 查询商品名称
	 * @param commodityId
	 * @return
	 */
	public Message<?> getCommodityName(Long commodityId) {
		String commodityName = commodityRepo.getNameByIdAndIsDeleted(commodityId);
		return new Message<>(CommodityResult.SUCCESS, commodityName);
	}
	
	/**
	 * 根据编号查询商品信息
	 * @param commodityId
	 * @return
	 */
	public Commodity getById(Long commodityId) {
		return commodityRepo.getByIdAndIsDeleted(commodityId, false);
	}
	
	/**
	 * 添加商品详情
	 * @param commodityAdds
	 * @throws IllegalAccessException 
	 * @throws ClassNotFoundException 
	 * @throws IllegalArgumentException 
	 */
	@Transactional
	public Message<?> add(CommodityAdds commodityAdds) throws IllegalArgumentException, ClassNotFoundException, IllegalAccessException {
		Commodity commodity = new Commodity();	
		/* 对类进行copy */
		BeanUtils.copyProperties(commodityAdds, commodity);
		if (commodityAdds.getShopId() == null) {
			logger.debug("商家商品业务处理类中(新增商品信息) ->  店铺ID为空");
			return new Message<>(CommodityResult.SHGOPNOTLOGIN);
		}
		/* 检验数据参数 */
		Message<?> message = ruleCheckService.commodityCheck(commodity);
		if (message.getCode() != 0) {
			return message;
		}
		try {
			/* 数据处理 */
			commodityEventHandler.beforeCreate(commodityAdds, commodity);
			commodityRepo.saveAndFlush(commodity);//保存数据
			invoicingRecordService.addInventoryRecord(commodity, commodityAdds.getShopId(),commodityAdds.getSupplierId());
			this.pushCommodity(commodity);
		} catch (Exception e) {
			logger.error("添加商品详情 . 添加异常", e);
			return new Message<>(CommodityResult.ERROR);
		}
		return new Message<>(CommodityResult.SUCCESS, commodity);
	}

	/**
	 * 保存商品数据
	 * @param commodity
	 */
	public void save(Commodity commodity) {
		commodityRepo.save(commodity);
	}

	/**
	 * 修改商品信息
	 * @param id
	 * @param commodityModifys
	 * @return
	 * @throws IllegalArgumentException
	 * @throws ClassNotFoundException
	 * @throws IllegalAccessException
	 */
	@Transactional
	public Message<?> update(Long id, CommodityModifys commodityModifys) throws IllegalArgumentException, ClassNotFoundException, IllegalAccessException {
		Commodity commodity = commodityRepo.findOne(id);
		logger.info("修改商品信息 . id【{}】查询 商品信息【{}】", id, commodity);
		BeanUtils.copyProperties(commodityModifys, commodity);
		logger.info("修改商品信息 . 属性值复制【{}】", commodity);
		/* 检验数据参数 */
		Message<?> message = ruleCheckService.commodityCheck(commodity);
		if (message.getCode() != 0) {
			return message;
		}
		commodityEventHandler.beforeSave(commodityModifys, commodity);
		logger.info("修改商品信息 . 数据处理修改添加前数据【{}】", commodity);
		commodityRepo.saveAndFlush(commodity);//保存数据
		invoicingCommodityNewService.update(commodity);//修改库存数据
		this.pushCommodity(commodity);//推送POS端
		return new Message<>(CommodityResult.SUCCESS);
	}
	
	/**
	 * 长链接推送商户信息
	 * @param commodity
	 * @return
	 */
	public Message<?> pushCommodity(Commodity commodity){
		CommodityReceive cr = new CommodityReceive(commodity.getType());
		BeanUtils.copyProperties(commodity, cr);
		boolean flag = pushService.sendCommodityMassage(new CommodityPushMessage(commodity.getMerchantId(), cr.getCommodity()));
		logger.info("推送商品信息 . 参数 推送是否成功【{}】",flag);
		if (commodity == null || flag == false) {
			logger.debug("商家商品业务处理类中(新增商品信息) ->  商品信息长链接推送失败");
			return new Message<>(CommodityResult.COMMODITYPUSH);
		}
		return new Message<>(CommodityResult.SUCCESS);
	}

	/**
	 * 商品批量删除
	 * @param ids
	 * @return
	 * @throws Exception
	 */
	public Message<?> delete(List<Long> ids) throws Exception {
		logger.info("商家商品业务处理类中(商品删除（逻辑删除）) ->  商品id 集合【{}】", ids);
		for (Long id : ids) {
			Message<?> message = this.delete(id);
			if (message.getCode() != 0) {
				return message;
			}
		}
		return new Message<>(CommodityResult.SUCCESS);
	}
	
	/**
	 * 商品删除
	 * @param id
	 * @return
	 * @throws Exception
	 */
	@Transactional
	public Message<?> delete(Long id) throws Exception {
		Commodity co = commodityRepo.findOne(id);
		if (co == null || co.getIsDeleted() == true) { //为空或已被逻辑删除
			logger.debug("商家商品业务处理类中(商品删除（逻辑删除）) ->  商家商品信息不存在或逻辑删除");
			return new Message<>(CommodityResult.COMMODITYNOTFIND);
		}
		Long splitRuleId = null;
		/* 删除商品时，移除拆分规则 */
		if (co.getIsDetachable() != null && co.getIsDetachable() == true){
			splitRuleId = co.getSplitRule().getId();//获取拆分规则ID
			splitCommodityRuleService.delete(splitRuleId);//DB删除拆分规则数据
			co.setIsDetachable(false);//商品信息设置为拆分为否
			co.setSplitRule(null);//移除拆分数据
		}
		/* 查询商品在拆分规则中对应信息 */
		List<SplitCommodityRule> scr = splitCommodityRuleService.findBySplitCommodity(id);
		if (scr != null && scr.size() > 0) {
			/* 删除被拆分商品时，将关联拆分后商品信息规则移除 */
			Long merchantId = co.getMerchantId();
			for (SplitCommodityRule splitCommodityRule : scr) {
				/* 获取被拆分规则 */
				List<Commodity> cos = commodityRepo.getByMerchantIdAndSplitRule(merchantId,splitCommodityRule);
				cos.stream().forEach(num -> num.setSplitRule(null));
				cos.stream().forEach(num -> num.setIsDetachable(false));
				commodityRepo.save(cos);
				splitCommodityRuleService.delete(splitCommodityRule.getId());
			}
		}
		co.setIsDeleted(true);//逻辑删除
		co.setUpdateDate(new Timestamp(System.currentTimeMillis()));
		co = commodityRepo.saveAndFlush(co);
		invoicingCommodityNewService.update(co);//修改库存数据
		this.pushCommodity(co);//推送POS端
		return new Message<>(CommodityResult.SUCCESS);
	}

}
